#ifndef _TCPCONNECTION_H
#define _TCPCONNECTION_H

#include "SocketIO.h"
#include "InetAddress.h"
#include "Socket.h"
#include <sstream>
#include <memory>
#include <functional>

using std::ostringstream;
using std::string;
using std::function;
using std::shared_ptr;

class EventLoop;
class TcpConnection 
:public std::enable_shared_from_this<TcpConnection>
{
public: 
    using TcpConnectionPtr = shared_ptr<TcpConnection>;
    using TcpConnectionCallback = function<void(const TcpConnectionPtr&)>;
    explicit TcpConnection(int fd,EventLoop* loop);
    void send(const string & msg);
    string receive();
    void sendTrain(const train_t& train);
    void recvTrain(train_t& train);
    bool isClosed();
    ~TcpConnection();
    
    //为了方便调试的函数
    string toString();
private:
    //获取本端地址和对端地址
    InetAddress getLocalAddr();
    InetAddress getPeerAddr();
public:
    //三种回调函数在EventLoop类中作为中转(这是三个事件)，在TcpConnection类中调用(这三个事件是与连接相关的)
    //使用左值引用,因为如果使用右值引用，EventLoop中的三个回调的数据成员只能使用一次，那么只能处理一个客户端连接
    void setNewConnectionCallback(const TcpConnectionCallback &cb); 
    void setMessageCallback(const TcpConnectionCallback &cb);
    void setCloseCallback(const TcpConnectionCallback &cb);
    
    //执行三个事件
    void handleNewConnectionCallback();
    void handleMessageCallback();
    void handleCloseCallback();

    void sendInLoop(const string &msg);  //目的是将具有发送数据能力send以及处理好的数据msg发给EventLoop
    void sendTrainInLoop(const train_t& train);  //目的是将具有发送数据能力send以及处理好的数据msg发给EventLoop
private:
    EventLoop* _loop;   //TcpConnection需要知道EventLoop存在，因为需要将处理好之后的数据发给EventLoop
    SocketIO _socketIO;
    //为了测试增加的数据成员
    Socket _sock;
    InetAddress _localAddr;
    InetAddress _peerAddr;
    //三个事件
    TcpConnectionCallback _onNewConnectionCb;
    TcpConnectionCallback _onMessageCb;
    TcpConnectionCallback _onCloseCb;
};

#endif //_TCPCONNECTION_H
